<template>
  <button
    :id="buttonId"
    @click="onclick"
    @touchstart="touchstart"
    @touchend="touchend"
    @longpress="emits('longpress', $event)"
    @touchcancel="touchcancel"
    @touchmove="emits('touchmove', $event)"
    @getphonenumber="emits('getphonenumber', $event)"
    @error="emits('error', $event)"
    @opensetting="emits('opensetting', $event)"
    @launchapp="emits('launchapp', $event)"
    @contact="emits('contact', $event)"
    @chooseavatar="emits('chooseavatar', $event)"
    :form-type="props.formType"
    :openType="props.openType"
    :appParameter="props.appParameter"
    :sessionFrom="props.sessionFrom"
    :sendMessageTitle="props.sendMessageTitle"
    :sendMessagePath="props.sendMessagePath"
    :sendMessageImg="props.sendMessageImg"
    :sendMessageCard="props.sendMessageCard"
    :loading="_load"
    :disabled="_disabled"
    :group-id="props.groupId"
    :guild-id="props.guildId"
    :public-id="props.publicId"
    :hover-start-time="10000000"
    hover-stop-propagation
    :class="[
      'button alipay flex flex-row flex-row-center-center',
      isclickOn && !_disabled && !_load ? props.hoverClass + ' bhover' : '',
      !_disabled && !_load ? 'webpc' : '',
      _load || _disabled ? 'opacity-8' : '',
      !isDisabledRoundAndriod ? `round-${btnSizeObj.round}` : '',
      customClass,
    ]"
    :style="[
      {
        marginLeft: _margin[0] + 'rpx',
        marginTop: _margin[1] + 'rpx',
        marginRight: _margin[2] + 'rpx',
        marginBottom: _margin[3] + 'rpx',
        paddingLeft: _padding[0] + 'rpx',
        paddingTop: _padding[1] + 'rpx',
        paddingRight: _padding[2] + 'rpx',
        paddingBottom: _padding[3] + 'rpx',
      },
      {
        height: btnSizeObj.h + props.unit,
        fontSize: btnSizeObj.fontSize + props.unit,
        color: textColor,
        lineHeight: btnSizeObj.h + props.unit,
      },
      btnSizeObj.w && !props.block ? { width: btnSizeObj.w + props.unit } : '',
      tmcomputed.borderCss,
      _bgcolor,
      !_transprent && _shadow > 0 && !props.text ? tmcomputed.shadowColor : '',
      customCSSStyle,
    ]"
  >
    <slot>
      <tm-icon
        :lineHeight="btnSizeObj.fontSize"
        v-if="_icon && !_load"
        :userInteractionEnabled="false"
        :color="_fontColor"
        :_class="_label ? 'pr-10' : ''"
        :unit="props.unit"
        :fontSize="btnSizeObj.fontSize"
        :name="_icon"
      ></tm-icon>
      <!-- #ifdef APP-NVUE -->
      <tm-text
        :color="props.fontColor"
        :font-size="btnSizeObj.fontSize"
        :unit="props.unit"
        :label="_label"
        _class="text-weight-b"
      ></tm-text>
      <!-- #endif -->
      <!-- #ifndef APP-NVUE -->
      {{ _label }}
      <!-- #endif -->
    </slot>
  </button>
</template>

<script lang="ts" setup>
  /**
   * 按钮
   * @description 属性与原生按钮一致，对于微信登录授权进行了便捷封装。
   * @slot default 默认插槽。
   */
  import { btnSize } from './interface';
  import { computed, PropType, ref, getCurrentInstance, provide } from 'vue';
  import tmSheet from '../tm-sheet/tm-sheet.vue';
  import tmText from '../tm-text/tm-text.vue';
  import tmIcon from '../tm-icon/tm-icon.vue';
  import { cssstyle, tmVuetify } from '../../tool/lib/interface';
  import {
    custom_props,
    computedTheme,
    computedClass,
    computedStyle,
    computedDark,
  } from '../../tool/lib/minxs';
  import { useTmpiniaStore } from '@/tmui/tool/lib/tmpinia';
  import theme from '@/tmui/tool/theme/theme';
  import { useDebounceFn } from '@/hooks/useDebounceFn';
  const store = useTmpiniaStore();

  /**
   * 事件说明
   * @description 事件属性与原生 一 致
   * @links 见官网：https://uniapp.dcloud.io/component/button.html
   */
  const emits = defineEmits<{
    (e: 'click', event: Event | TouchEvent): void;
    (e: 'touchstart', event: Event | TouchEvent): void;
    (e: 'touchmove', event: Event | TouchEvent): void;
    (e: 'touchcancel', event: Event | TouchEvent): void;
    (e: 'touchend', event: Event | TouchEvent): void;
    (e: 'tap', event: Event | TouchEvent): void;
    (e: 'longpress', event: Event | TouchEvent): void;
    (e: 'getphonenumber', event: any): void;
    (e: 'getUserInfo', event: any): void;
    (e: 'getUserProfile', event: any): void;
    (e: 'error', event: any): void;
    (e: 'opensetting', event: any): void;
    (e: 'launchapp', event: any): void;
    (e: 'contact', event: any): void;
    (e: 'chooseavatar', event: any): void;
  }>();
  const isnvue = ref(false);
  // #ifdef APP-NVUE
  isnvue.value = true;
  // #endif
  const proxy = getCurrentInstance()?.proxy ?? null;
  const props = defineProps({
    ...custom_props,
    transparent: {
      type: Boolean,
      default: false,
    },
    followTheme: {
      type: Boolean,
      default: true,
    },
    hoverClass: {
      type: String,
      default: 'opacity-7',
    },
    /**
     * mini,small,normal,middle,large
     */
    size: {
      type: String as PropType<btnSize>,
      default: 'normal',
    },
    fontSize: {
      type: Number,
      default: 0,
    },
    fontColor: {
      type: String,
      default: '',
    },
    margin: {
      type: Array as PropType<Array<number>>,
      default: () => [0, 16],
    },
    padding: {
      type: Array as PropType<Array<number>>,
      default: () => [0, 0],
    },
    //不是同层背景，默认是同层，为false
    //如果输入框表单与tmshee在同一层下。他们的黑白暗黑背景色是相同的。为了区分这个问题，需要单独指示，以便区分背景同层。
    //主意：它只在黑和白之间的色系才起作用，其它颜色下不起作用。
    noLevel: {
      type: Boolean,
      default: false,
    },
    shadow: {
      type: Number,
      default: 0,
    },
    width: {
      type: Number,
      default: 0,
    },
    height: {
      type: Number,
      default: 0,
    },
    //如果为true，采用块状flex布局，自动宽和高度。
    block: {
      type: Boolean,
      default: false,
    },
    round: {
      type: Number,
      default: 0,
    },
    loading: {
      type: Boolean,
      default: false,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    //提供时，点击后会中转到对应页面。
    url: {
      type: String,
      default: '',
    },
    label: {
      type: String,
      default: '',
    },
    icon: {
      type: String,
      default: '',
    },
    /**
     * submit,reset 在tm-form中使用。
     */
    formType: {
      type: String as PropType<'submit' | 'reset' | 'filterCancel' | 'filterConfirm'>,
      default: '',
    },
    //开放能力
    openType: {
      type: String as PropType<
        | 'contact'
        | 'share'
        | 'getPhoneNumber'
        | 'getRealtimePhoneNumber'
        | 'getUserInfo'
        | 'launchApp'
        | 'openSetting'
        | 'feedback'
        | 'chooseAvatar'
        | 'agreePrivacyAuthorization'
      >,
      default: '',
    },
    /** 按钮的id */
    buttonId: {
      type: String,
    },
    //打开 APP 时，向 APP 传递的参数，open-type=launchApp时有效
    appParameter: {
      type: String,
      default: '',
    },
    sessionFrom: {
      type: String,
      default: '',
    },
    sendMessageTitle: {
      type: String,
      default: '',
    },
    sendMessagePath: {
      type: String,
      default: '',
    },
    sendMessageImg: {
      type: String,
      default: '',
    },
    sendMessageCard: {
      type: String,
      default: '',
    },
    groupId: {
      type: String,
      default: '',
    },
    guildId: {
      type: String,
      default: '',
    },
    publicId: {
      type: String,
      default: '',
    },
    unit: {
      type: String,
      default: 'rpx',
    },
    darkBgColor: {
      type: String,
      default: '',
    },
    /**禁用后的主题色 */
    disabledColor: {
      type: String,
      default: 'grey-1',
    },
  });

  /** -----------form专有------------ */
  const formtype = computed(() => props.formType);
  //父级方法。
  let FormParent: any = null;
  let FilterParent: any = null;
  if (formtype.value == 'reset' || formtype.value == 'submit') {
    FormParent = proxy?.$parent;
    while (FormParent) {
      if (FormParent?.tmFormComnameId == 'tmFormId' || !FormParent) {
        break;
      } else {
        FormParent = FormParent?.$parent ?? undefined;
      }
    }
  }
  //过滤器菜单 专用属性.
  if (formtype.value == 'filterCancel' || formtype.value == 'filterConfirm') {
    FilterParent = proxy?.$parent;
    while (FilterParent) {
      if (FilterParent?.FilterMenu == 'FilterMenu' || !FilterParent) {
        break;
      } else {
        FilterParent = FilterParent?.$parent ?? undefined;
      }
    }
  }
  /** -----------end------------ */
  const _noLevel = computed(() => props.noLevel);
  //是否暗黑模式。
  const isDark = computed(() => computedDark(props, tmcfg.value));
  // 设置响应式主题文字色。
  let textColor = computed(() => {
    if (theme.isCssColor(_fontColor.value)) return _fontColor.value;
    if (!props.fontColor) return tmcomputed.value.textColor;
    return theme.getColor(props.fontColor).value;
  });
  //自定义样式：
  const customCSSStyle = computed(() => {
    return {
      // height: btnSizeObj.value.h + props.unit,
      ...computedStyle(props),
      // fontSize:props.fontSize,
      // color:textColor,
      // border: "0px solid rgba(0, 0, 0, 0)",
      // background: "rgba(0, 0, 0, 0)",
      // borderRadius: "0px",
    };
  });
  //自定类
  const customClass = computed(() => computedClass(props));
  // 设置响应式全局组件库配置表。
  const tmcfg = computed(() => store.tmStore);
  //计算主题
  const _shadow = computed(() => props.shadow || 0);
  const tmcomputed = computed<cssstyle>(() => {
    let nprops = { ...props, shadow: _shadow.value };
    if (_disabled.value) {
      nprops.color = props.disabledColor;
    }

    return computedTheme({ ...nprops }, isDark.value, tmcfg.value);
  });

  const isclickOn = ref(false);
  const _load = computed(() => props.loading);
  const _disabled = computed(() => props.disabled);
  const _label = computed(() => props.label);
  const _icon = computed(() => props.icon);
  const _isBorder = computed(() => {
    if (props.outlined && props.border == 0) return 1;
    if (props.border > 0) return props.border;
    return 0;
  });
  const sizeObj = computed(() => {
    let ptest = {
      block: { w: 0, h: 80, fontSize: 28, round: 3 },
      mini: { w: 88, h: 36, fontSize: 20, round: 3 },
      small: { w: 120, h: 56, fontSize: 22, round: 3 },
      normal: { w: 220, h: 80, fontSize: 28, round: 3 },
      middle: { w: 300, h: 80, fontSize: 30, round: 3 },
      large: { w: 375, h: 80, fontSize: 32, round: 3 },
    };
    if (props.unit == 'px') {
      let key: 'block' | 'mini' | 'small' | 'normal' | 'middle' | 'large' = 'block';
      let key2: 'w' | 'h' | 'fontSize' | 'round' = 'w';
      for (key in ptest) {
        for (key2 in ptest[key]) {
          ptest[key][key2] = uni.upx2px(ptest[key][key2]);
        }
      }
    }
    return ptest;
  });
  const btnSizeObj = computed(() => {
    let fontSize = props.fontSize || 0;
    if (props.block) {
      return {
        w: 0,
        h: props.height || sizeObj.value.block.h,
        fontSize: fontSize || sizeObj.value.block.fontSize,
        round:
          props.round == -1
            ? 0
            : props.round ||
              (store.tmuiConfig.themeConfig?.component?.button?.round ?? 0) ||
              sizeObj.value.normal.round,
      };
    }
    return {
      w: props.width || sizeObj.value[props.size].w,
      h: props.height || sizeObj.value[props.size].h,
      fontSize: fontSize || sizeObj.value[props.size].fontSize,
      round:
        props.round == -1
          ? 0
          : props.round ||
            (store.tmuiConfig.themeConfig?.component?.button?.round ?? 0) ||
            sizeObj.value[props.size].round,
    };
  });
  const _fontColor = computed(() => props.fontColor);
  const _transprent = computed(() => props.transparent);
  /** 数组是左，上，右，下顺序。 */
  const _margin = computed(() => {
    if (props.margin.length == 1)
      return [props.margin[0], props.margin[0], props.margin[0], props.margin[0]];
    if (props.margin.length == 2)
      return [props.margin[0], props.margin[1], props.margin[0], props.margin[1]];
    if (props.margin.length == 3) return [props.margin[0], props.margin[1], props.margin[2], 0];
    if (props.margin.length == 4)
      return [props.margin[0], props.margin[1], props.margin[2], props.margin[3]];
    return [0, 0, 0, 0];
  });
  const _padding = computed(() => {
    if (props.padding.length == 1)
      return [props.padding[0], props.padding[0], props.padding[0], props.padding[0]];
    if (props.padding.length == 2)
      return [props.padding[0], props.padding[1], props.padding[0], props.padding[1]];
    if (props.padding.length == 3) return [props.padding[0], props.padding[1], props.padding[2], 0];
    if (props.padding.length == 4)
      return [props.padding[0], props.padding[1], props.padding[2], props.padding[3]];
    return [0, 0, 0, 0];
  });

  const _bgcolor = computed(() => {
    if (_transprent.value === true) return `background-color:rgba(255,255,255,0);`;
    if (props.darkBgColor !== '' && isDark.value === true) {
      return `background-color:${props.darkBgColor};`;
    }
    if (props.linearColor.length == 2) {
      return {
        'background-image': `linear-gradient(${tmcomputed.value.linearDirectionStr},${props.linearColor[0]},${props.linearColor[1]})`,
      };
    }
    if (tmcomputed.value.gradientColor?.length == 2) {
      return tmcomputed.value.backgroundColorCss;
    }

    if (_noLevel.value && tmcomputed.value.isBlackAndWhite === true && isDark.value === true) {
      return `background-color: ${tmcomputed.value.inputcolor}`;
    }
    return `background-color: ${tmcomputed.value.backgroundColor}`;
  });

  function touchstart(e: Event) {
    isclickOn.value = true;
    emits('touchstart', e);
  }
  function touchend(e: Event) {
    isclickOn.value = false;
    emits('touchend', e);
  }
  function touchcancel(e: Event) {
    isclickOn.value = false;
    emits('touchcancel', e);
  }

  const onclick = useDebounceFn(function (e: Event) {
    if (
      FormParent != null &&
      typeof FormParent != 'undefined' &&
      formtype.value &&
      !props.loading
    ) {
      FormParent[formtype.value]();
    }
    if (
      FilterParent != null &&
      typeof FilterParent != 'undefined' &&
      formtype.value &&
      !props.loading
    ) {
      FilterParent[formtype.value]();
    }
    // if button loading , not handle click
    if (props.loading) return;

    emits('click', e);
    if (props.url !== '' && typeof props.url === 'string') {
      let url = props.url;
      if (url[0] !== '/') url = '/' + url;
      uni.navigateTo({
        url: url,
      });
      return;
    }
    if (props.openType == 'getUserInfo' || props.openType == 'getUserProfile') {
      // #ifdef MP-WEIXIN
      uni.getUserProfile({
        desc: '用于完善会员资料',
        success: function (userProfile) {
          if (userProfile.errMsg != 'getUserProfile:ok') {
            uni.showToast({
              title: userProfile.errMsg,
              icon: 'error',
              mask: true,
            });
            return;
          }
          emits('getUserInfo', userProfile);
          emits('getUserProfile', userProfile);
        },
        fail: (error) => {
          console.log(error);
          uni.showToast({
            icon: 'none',
            title: typeof error == 'object' ? error.errMsg : error,
          });
        },
      });
      console.warn(
        "微信小程序已收回‘getUserProfile’以及‘getUserInfo’权限，请使用open-type='chooseAvatar'使用@chooseavatar回调，详见《微信小程序用户头像昵称获取规则调整公告》https://developers.weixin.qq.com/community/develop/doc/00022c683e8a80b29bed2142b56c01",
      );
      // #endif
    }
  }, 500);

  provide('appTextColor', textColor);
</script>

<style scoped>
  .button {
    /* background: rgba(0, 0, 0, 0); */
    /* border: 0px solid rgba(0, 0, 0, 0); */
    padding: 0px;
    /* border-radius: 0px; */
    line-height: inherit !important;
  }

  .buttonHover {
    /* background: rgba(0, 0, 0, 0); */
  }

  .bhover {
    opacity: 0.7;
  }

  /* #ifdef H5 */
  /* .webpc:hover {
  cursor: pointer;
  opacity: 0.7;
} */
  /* #endif */
  /* #ifndef APP-NVUE */
  /* .bhover:hover {
  opacity: 0.7 !important;
} */
  .button::after {
    background: transparent !important;
    background-color: transparent !important;
    border: none !important;
    border-radius: 0px !important;
  }

  /* #endif */
  /* #ifdef MP */
  .button.alipay {
    transition: opacity 0.7s;
  }

  /* #endif */
</style>
